from sys import argv
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *

class MyPyOpenGLTest:
    def __init__(self, width=640, height=480, title='旋转的三次Bezier曲线'):
        glutInit(len(argv), argv)
        glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH)
        glutInitWindowSize(width, height)
        glutInitWindowPosition(350, 200)
        self.window = glutCreateWindow(title.encode('gbk'))
        glutDisplayFunc(self.draw)
        glutIdleFunc(self.draw)
        
        # 初始化窗口背景为白色
        glClearColor(1, 1, 1, 1)
        # 透视投影变换
        glMatrixMode(GL_PROJECTION)
        gluPerspective(45.0, width/height, 0.1, 100)
        glMatrixMode(GL_MODELVIEW)
        # 指定三次贝塞尔曲线的4个控制点坐标
        self.control_points = [(-4, -2, -9), (-0.5, 3, 0),
                               (2, -3, 0), (4.5, 2, 0)]
        self.angle = 0
        
    # 计算三次贝塞尔曲线上指定参数对应的点坐标
    def getBezier(self, P0, P1, P2, P3, t):
        a0 = (1 - t) ** 3
        a1 = 3 * (1 - t) ** 2 * t
        a2 = 3 * t ** 2 * (1 - t)
        a3 = t ** 3

        x = a0*P0[0] + a1*P1[0] + a2*P2[0] + a3*P3[0]
        y = a0*P0[1] + a1*P1[1] + a2*P2[1] + a3*P3[1]
        z = a0*P0[2] + a1*P1[2] + a2*P2[2] + a3*P3[2]
        return (x, y, z)

    def draw(self):

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
        glMatrixMode(GL_MODELVIEW)
        glLoadIdentity()

        # 平移
        glTranslatef(0.0, 0.0, -26.0)
        # 旋转
        glRotatef(self.angle, 1, 1, 0)
        self.angle = self.angle + 1
        # 给控制点
        glColor3f(1, 1, 0)
        glPointSize(8)
        glBegin(GL_POINTS)
        for point in self.control_points:
            glVertex3fv(point)
        glEnd()
        # 绘制控制多边形
        glColor3f(0, 1, 0.5)
        glLineWidth(2)
        glBegin(GL_LINE_STRIP)
        for point in self.control_points:
            glVertex3fv(point)
        glEnd()
        # 绘制Bezier曲线
        glColor3f(0.0, 0.0, 0.0)
        glLineWidth(3)
        glBegin(GL_LINE_STRIP)
        for i in range(1001):
            t = i / 1000
            p = self.getBezier(*self.control_points, t)
            glVertex3fv(p)
        glEnd()

        # 交换缓冲区，更新图形
        glutSwapBuffers()

    # 消息主循环
    def mainloop(self):
        glutMainLoop()

if __name__ == '__main__':
    MyPyOpenGLTest().mainloop()
